package com.gxa.modules.shiro;

import com.gxa.modules.mapper.RoleMapper;
import com.gxa.modules.mapper.ShiroMapper;
import com.gxa.modules.pojo.R_Menu;
import com.gxa.modules.pojo.R_Role;
import com.gxa.modules.pojo.R_User;
import com.gxa.modules.service.ShiroService;
import com.gxa.modules.service.UserService;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 认证
 *
 */
@Component
public class MyRealm extends AuthorizingRealm {

        @Autowired
        private UserService userService;

        @Autowired(required = false)
        private RoleMapper roleMapper;
    /**
     * 认证的方法
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("===========认证=============");
        //获取用户名
        String userName = (String) authenticationToken.getPrincipal();
        //通过用户名获取密码
        String userPwd = getPwdByUserName(userName).getUser_password();
        //通过用户名获取盐值
        String salt = getPwdByUserName(userName).getSalt();
        if(userPwd != null){
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(userName,userPwd,"myRealm");
            //加盐
            info.setCredentialsSalt(ByteSource.Util.bytes(salt));
            System.out.println("认证账户"+userName);
            System.out.println("认证密码"+userPwd);
            return info;
        }
        return null;
    }

    /**
     * 根据用户名查询密码
     * @param userName
     * @return
     */
    private R_User getPwdByUserName(String userName) {
        //调用Service查询
        R_User user = userService.findByUserName(userName);
        if(user != null){
            return user;
        }
        return null;
    }
    /**
     *  授权的方法
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("===========授权=============");
        //1、获取用户名
        String userName = (String) principalCollection.getPrimaryPrincipal();
        //2、获取用户对象
        R_User user =  userService.findByUserName(userName);
        //3、根据用户对象查找对应的角色
        List<R_Role> rolesList = roleMapper.findRoleByUser(user.getUser_id());
        Set<String> roles = getRolesByUser(rolesList);
        //4、获取权限数据
        Set<String> permissions = getPermissionByRole(rolesList);
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //设置角色和权限数据
        info.setRoles(roles);
        info.setStringPermissions(permissions);
        return info;
    }


    /**
     * 根据角色查找对应的权限
     * @param roles
     * @return
     */
    private Set<String> getPermissionByRole(List<R_Role> roles) {
        if (roles.isEmpty() || roles == null){
            return null;
        }
        Set<String> sets = new HashSet<>();
        List<Long> listRoleId = new ArrayList<>();
        for (R_Role role :roles) {
            listRoleId.add(role.getRole_id());
        }
        List<R_Menu> permissionList = roleMapper.findMenuByRoleId(listRoleId);
        if (permissionList == null || permissionList.isEmpty()){
            return null;
        }
        for (R_Menu p : permissionList) {
            sets.add(p.getTitle());
        }
        return sets;
    }

    /**
     * 根据用户查找对应的角色
     * @param
     * @return
     */
    private Set<String> getRolesByUser(List<R_Role> rolesList) {
        if(rolesList != null || !rolesList.isEmpty()){
            Set<String> setRoles = new HashSet<>();
            for (R_Role r:rolesList) {
                setRoles.add(r.getRolename());
            }
            return setRoles;
        }
        return null;
    }
}
